package settings

import (
	"fmt"
	"github.com/fsnotify/fsnotify"
	"github.com/spf13/viper"
)

// Conf 全局配置信息变量, 保存项目所有配置信息
var Conf = new(AppConfig) // new()返回的结构体变量是指针类型

type AppConfig struct {
	Name         string `mapstructure:"name"`
	Mode         string `mapstructure:"mode"`
	Version      string `mapstructure:"version"`
	Port         int    `mapstructure:"port"`
	KeyMd5       string `mapstructure:"key_md5"`
	*JWT         `mapstructure:"jwt"`
	*LogConfig   `mapstructure:"log"`
	*MySQLConfig `mapstructure:"mysql"`
	*RedisConfig `mapstructure:"redis"`
	*SnowFlake   `mapstructure:"snowflake"`
}

type JWT struct {
	Name   string `mapstructure:"name"`
	Expire int    `mapstructure:"expire"`
}

type LogConfig struct {
	Level      string `mapstructure:"level"`
	Filename   string `mapstructure:"filename"`
	MaxSize    int    `mapstructure:"max_size"`
	MaxAge     int    `mapstructure:"max_age"`
	MaxBackups int    `mapstructure:"max_backups"`
}

type MySQLConfig struct {
	Host         string `mapstructure:"host"`
	User         string `mapstructure:"user"`
	Password     string `mapstructure:"password"`
	DbName       string `mapstructure:"dbname"`
	Port         int    `mapstructure:"port"`
	MaxOpenConns int    `mapstructure:"max_open_conns"`
	MaxIdleConns int    `mapstructure:"max_idle_conns"`
}

type RedisConfig struct {
	Host     string `mapstructure:"host"`
	Password string `mapstructure:"password"`
	Port     int    `mapstructure:"port"`
	DB       int    `mapstructure:"db"`
	PoolSize int    `mapstructure:"pool_size"`
}

type SnowFlake struct {
	StartTime string `mapstructure:"start_time"`
	MachineID int64  `mapstructure:"machine_id"`
}

func Init() (err error) {
	// viper.SetConfigFile("config.yaml") // 含后缀名,选取指定文件
	viper.SetConfigName("config")   // 配置文件名称(不含后缀名,搜索到相同名称文件选取第一个)
	viper.SetConfigType("yaml")     // 配置文件扩展名(专用于从远程获取配置信息时指定文件类型)
	viper.AddConfigPath("./config") // 工作目录中查找配置(相对路径,项目运行命令目录)
	// 读取配置信息
	if err = viper.ReadInConfig(); err != nil { // 读取配置信息失败处理
		fmt.Printf("viper read config failed, %s\n", err)
		panic(fmt.Errorf("fatal error config file: %s\n", err))
	}
	// 将读取到的配置信息反序列化到 Conf 变量中
	if err = viper.Unmarshal(Conf); err != nil {
		fmt.Printf("viper.Unmarshal failed, err:#{err}\n")
	}
	viper.WatchConfig()                           // 监听配置文件
	viper.OnConfigChange(func(e fsnotify.Event) { // 配置文件被修改后执行方法
		fmt.Println("配置文件被修改")
		if err = viper.Unmarshal(Conf); err != nil {
			fmt.Printf("viper.Unmarshal failed, err:#{err}\n")
		}
	})
	return
}
